package com.inifitness.tenant.core.config.mp.aspect;

import java.lang.reflect.Method;
import java.util.Objects;

import com.inifitness.tenant.core.config.mp.annotation.IgnoreTenant;
import com.inifitness.tenant.core.config.mp.handler.MybatisTenantContext;

import lombok.extern.log4j.Log4j2;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.annotation.AnnotationUtils;

/**
 * TODO: (sunjinfeng 2024-05-09)
 *
 * @author sunjinfeng
 * @version 1.0.0
 * @since 2024-05-09 10:49
 */
@Log4j2
public class TenantIgnoreAspect {

  /**
   * 切入点
   */
  @Pointcut("@within(com.inifitness.tenant.core.config.mp.annotation.IgnoreTenant) ||@annotation(com.inifitness.tenant.core.config.mp.annotation.IgnoreTenant)")
  public void pointcut() {
    log.info("定义忽略租户隔离切点");
  }

  @Around("pointcut()")
  public Object around(ProceedingJoinPoint point) throws Throwable {
    try {
      Class<?> targetClass = point.getTarget().getClass();
      IgnoreTenant classIgnoreTenant = targetClass.getAnnotation(IgnoreTenant.class);
      MethodSignature signature = (MethodSignature) point.getSignature();
      Method method = signature.getMethod();
      IgnoreTenant methodIgnoreTenant = method.getAnnotation(IgnoreTenant.class);

      //判断类上是否有注解
      boolean isClassAnnotated = AnnotationUtils.isAnnotationDeclaredLocally(IgnoreTenant.class,
          targetClass);
      //判断方法上是否有注解
      boolean isMethodAnnotated = Objects.nonNull(methodIgnoreTenant);

      //如果类上有
      if (isClassAnnotated) {
        MybatisTenantContext.set(classIgnoreTenant.ignore());
      }
      //如果方法上有 以方法上的为主
      if (isMethodAnnotated) {
        MybatisTenantContext.set(methodIgnoreTenant.ignore());
      }
      Object result = point.proceed();
      return result;
    } finally {
      MybatisTenantContext.clear();
    }
  }
}
